import os

from django.http import FileResponse
from django.core.exceptions import ObjectDoesNotExist
from django_filters.rest_framework import DjangoFilterBackend

from rest_framework import viewsets
from rest_framework.filters import OrderingFilter,SearchFilter
from rest_framework import status
from rest_framework.response import Response

from XApiTestServer.serializers import FileSerializer
from XApiTestServer.pagination import MyPageNumberPagination
from XApiTestServer.utils.common import *
from XApiTestServer.utils.test_report import *
from XApiTestServer.utils.response import *
from XApiTestServer.utils.auth import get_username
from XApiTestServer.utils.file_opt import *


def add_file_data(**kwargs):
    """
    #上传文件落地
    :param kwargs:
    :return:
    """
    """
    :param kwargs:
    :return:
    """

    try:
        if FileInfo.objects.filter(project=kwargs.get('project'), module=kwargs.get('module'), name=kwargs.get('name')).count() > 0:
            return '文件已存在，请重新上传'
        FileInfo.objects.create(**kwargs)
        logging.info('文件添加成功: {kwargs}'.format(kwargs=kwargs))
    except Exception as e:
        return '文件上传异常，请重试'
    return 'ok'


class FileViewSet(viewsets.ModelViewSet):
    queryset = FileInfo.objects.all()
    serializer_class = FileSerializer
    pagination_class = MyPageNumberPagination
    filter_backends = (OrderingFilter, SearchFilter, DjangoFilterBackend)
    search_fields = ('name',)
    filterset_fields = ('project', 'module',)
    ordering_fields = ('update_time', )

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()

        file_index = instance.id
        file_path = instance.file_path
        file_name = instance.name
        file_path = os.path.join(settings.BASE_DIR, file_path)
        logger.info("Download File Index: {},File Name: {}".format(file_index,file_name))
        if not os.path.exists(file_path):
            return Response(FILE_NOT_EXISTS, status=status.HTTP_201_CREATED)
        response = FileResponse(open(file_path, 'rb'))
        response['Content-Type'] = 'application/octet-stream'

        return response

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        try:
            self.perform_destroy(instance)
            file_path = instance.file_path
            file_name = instance.name
            objfile = os.path.join(settings.BASE_DIR, file_path)
            logger.info("Delete File: {}".format(file_name))
            if os.path.exists(objfile):
                os.remove(objfile)
        except ObjectDoesNotExist:
            return Response(FILE_NOT_EXISTS, status=status.HTTP_201_CREATED)
        response_body = SUCCESS_DEL
        return Response(response_body)

    def create(self, request, *args, **kwargs):
        if request.data['module'] == '' or request.data['project'] == '' or len(request.FILES.getlist('file')) == 0:
            return Response(VERIFY_FIELDS_HINT, status=status.HTTP_201_CREATED)

        project_id = request.POST.get('project')
        module_id = request.POST.get('module')
        project_name = ProjectInfo.objects.get(id=project_id).project_name
        module_name = ModuleInfo.objects.get(id=module_id).module_name

        token = request.META.get("HTTP_X_TOKEN", None)
        username=get_username(token)

        upload_path = os.path.join(settings.BASE_DIR, "upload", project_name, module_name)
        if not os.path.exists(upload_path):
            os.makedirs(upload_path)
        upload_obj = request.FILES.getlist('file')
        failed_list = []
        exists_list = []
        for f in upload_obj:
            temp_path = os.path.join(upload_path, f.name)
            logger.info("Upload File: {}".format(f.name))
            if os.path.exists(temp_path):
                exists_list.append(f.name)
            try:
                with open(temp_path, 'wb') as data:
                    for line in f.chunks():
                        data.write(line)
            except IOError as e:
                failed_list.append(f.name)
                continue
            # 转换文件格式
            try:
                change_file_encoding(temp_path)
            except:
                pass
            file_info = {
                "belong_project": project_name,
                "belong_module": module_name,
                "project" : ProjectInfo.objects.get_pro_name(project_name, False),
                "module" : ModuleInfo.objects.get(id=module_id),
                "name": f.name,
                "author": username,
                "file_size": len(f),
                "file_path": os.path.join("upload", project_name, module_name, f.name)
            }
            msg = add_file_data(**file_info)
            if msg != "ok":
                failed_list.append(f.name)
                continue

        if failed_list:
            print(failed_list)
            failed_data = '上传失败，失败文件为 {failed_list},其中文件{exists_list}已存在，请确认后再操作'  .format(failed_list=failed_list, exists_list=exists_list)
            response_body = FILE_UPLOAD_FAILED
            response_body['msg'] = failed_data
            return Response(response_body, status=status.HTTP_201_CREATED)
        else:
            response_body = FILE_UPLOAD_SUCCESS
            return Response(response_body, status=status.HTTP_200_OK)
